import React from 'react';
import moment from 'moment';
import { Button, message, Popover, Select } from 'antd';
import _ from 'lodash';
import { connect } from 'react-redux';
import PropTypes from 'prop-types';
import { bindActionCreators } from 'redux';
import cn from 'classnames';

import { getOneDayList, getVulnerabilityList } from '@api/task';
import {
  downloadAssetForm,
  exportAssetForm,
  loadAssets,
  exportChangeForm,
  downloadChangeForm
} from '@api/asset';
import {
  CONSOLE_LEVEL_ICON_MAP,
  CONSOLE_ONEDAY_DISABLE_COLOR,
  LEVEL_COLOR,
  LEVEL_TEXT,
  LEVEL_TYPES
} from '@util/constants';
import OnedayTaskModal from '@components/custom-oneday-modal';
import SitesChangeCard from '@containers/console/components/sites-change-card';
import { actions as assetManageActions } from '@containers/asset-manage/reducer';

import {
  DetectSvg,
  DownloadAllSvg,
  DownloadSvg,
  JumpSvg,
  NewAddSvg,
  RiskComponentSvg,
  RiskPortSvg,
  RiskServiceSvg,
  RiskSvg,
  SafeSvg,
  SuspectedSvg,
  UnUpdatedSvg,
  UpdateSvg,
  VerifySvg,
  VulInformationSvg,
  VulSvg
} from './images';
import ListCard from './components/ListCard';
import DetectionTaskModal from '../asset-manage/components/detection-task-modal';
import './index.less';

const TimeRangeMap = {
  1: '今日',
  7: '近7日',
  30: '近30日'
};

// 按照分组纵向排列
const riskCardConfigs = [
  [
    {
      dataKey: 'withVulSite',
      title: '存在漏洞的资产'
    },
    {
      dataKey: 'withVulInfo',
      title: '与资产有关的情报'
    },
    {
      dataKey: 'withSuspectedVulSite',
      title: '有疑似漏洞的资产'
    }
  ],
  [
    {
      dataKey: 'withBlackPortSite',
      title: '存在关键端口的资产'
    },
    {
      dataKey: 'withBlackServiceSite',
      title: '存在关键服务的资产'
    },
    {
      dataKey: 'withBlackComponentSite',
      title: '存在关键组件的资产'
    }
  ],
  [
    {
      dataKey: 'unUpdatedSite1',
      title: `${TimeRangeMap[1]}未更新的资产`
    },
    {
      dataKey: 'unUpdatedSite7',
      title: `${TimeRangeMap[7]}未更新的资产`
    },
    {
      dataKey: 'unUpdatedSite30',
      title: `${TimeRangeMap[30]}未更新的资产`
    }
  ],
  [
    {
      dataKey: 'newSite1',
      title: `${TimeRangeMap[1]}新增资产`
    },
    {
      dataKey: 'newSite7',
      title: `${TimeRangeMap[7]}新增资产`
    },
    {
      dataKey: 'newSite30',
      title: `${TimeRangeMap[30]}新增资产`
    }
  ],
  [
    {
      dataKey: 'updatedSite1',
      title: `${TimeRangeMap[1]}变更的资产日志`
    },
    {
      dataKey: 'updatedSite7',
      title: `${TimeRangeMap[7]}变更的资产日志`
    },
    {
      dataKey: 'updatedSite30',
      title: `${TimeRangeMap[30]}变更的资产日志`
    }
  ]
];

class Console extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      lastUpdatedAt: Date.now(),
      riskPorts: [],
      riskComponents: [],
      riskServices: [],
      assetCategoryNameMap: {},
      countMap: {},
      onedayTaskModalConfig: {
        visible: false,
        strategy: 'affected'
      },
      allFormConfig: {},
      detectionModalType: '',
      detectionSiteQuery: {},
      ips: [],
      hasOneDayModule: false, // 如果没有1day模块，屏蔽与漏洞相关部分
      notUpdatedTime: 7
    };
    this.timer = null;
    this.ListCardRef = {};
  }

  componentDidMount() {
    const { modules = [] } = this.props;
    const hasOneDayModule = modules.includes('1day');
    this.setState({
      hasOneDayModule
    });
    this.getVulnerabilityList();
    this.timer = window.setInterval(() => {
      this.setState({ lastUpdatedAt: Date.now() });
    }, 30 * 60 * 1000);
  }

  componentWillUnmount() {
    if (this.timer) {
      window.clearInterval(this.timer);
    }
  }

  getVulnerabilityList() {
    getVulnerabilityList().then(res => {
      const vuls = _.get(res, 'data.data.list', []);
      const riskPorts = _.map(_.filter(vuls, { type: 'port' }), i => Number(i.name));
      const riskComponents = _.map(_.filter(vuls, { type: 'component' }), 'name');
      const riskServices = _.map(_.filter(vuls, { type: 'service' }), 'name');
      this.setState({
        riskComponents,
        riskPorts,
        riskServices,
        lastUpdatedAt: Date.now()
      });
    });
  }

  getRiskSites = (pagaition, queryKey, countKey) => {
    let risks;
    if (queryKey === 'port') {
      risks = this.state.riskPorts;
    } else if (queryKey === 'component') {
      risks = this.state.riskComponents;
    } else if (queryKey === 'service') {
      risks = this.state.riskServices;
    }

    if (_.isEmpty(risks)) {
      return Promise.resolve([0, []]);
    } else {
      return this.getSites({ pagaition, query: { [queryKey]: risks }, key: countKey });
    }
  };

  getOneday = filter => {
    return getOneDayList({
      ...filter,
      real: 'down',
      suspect: 'down',
      updated: 'down'
    }).then(res => {
      const count = _.get(res, 'data.data.count', 0);
      const affectSiteCount = _.get(res, 'data.data.affectSiteCount', 0);
      const list = _.get(res, 'data.data.list', []);
      this.setState(state => {
        const countMap = _.get(state, 'countMap') || {};
        countMap['withVulInfo'] = affectSiteCount;
        return { countMap };
      });
      return [count, list, affectSiteCount];
    });
  };

  getSites = ({ pagaition = { page: 1, pageSize: 10 }, query, sort, key, timeNow }) => {
    return loadAssets({
      pagaition,
      query,
      sort: sort || {
        by: 'risk',
        direction: -1
      }
    }).then(res => {
      const count = _.get(res, 'data.data.count', 0);
      const list = _.get(res, 'data.data.list', []);
      if (timeNow) {
        let ips = list.map(item => item.ip || item.domain);
        this.setState({ ips });
        return;
      }
      this.setState(state => {
        const countMap = _.get(state, 'countMap') || {};
        countMap[key] = count;
        return { countMap };
      });
      return [count, list];
    });
  };

  getSiteOrJumper = (key, values) => {
    return (
      <a
        key="jump"
        target="_blank"
        rel="noopener noreferrer"
        href={`/asset-manage?${encodeURIComponent(
          values.map(v => `exact:${key}="${v}"`).join(' || ')
        )}`}
      >
        <img src={JumpSvg} alt="jump" />
      </a>
    );
  };

  getSiteRangeJumper = (key, values) => {
    return (
      <a
        key="jump"
        target="_blank"
        rel="noopener noreferrer"
        href={`/asset-manage?${encodeURIComponent(`${key}="${values.join(',')}"`)}`}
      >
        <img src={JumpSvg} alt="jump" />
      </a>
    );
  };

  getOneDayJumper = () => {
    return (
      <a key="jump" target="_blank" rel="noopener noreferrer" href={'/vul/oneday-detection'}>
        <img src={JumpSvg} alt="jump" />
      </a>
    );
  };

  exportAssetForm = (query, description, showSuccess = true) => {
    return exportAssetForm({
      query: query,
      sort: {
        by: 'risk',
        direction: -1
      },
      description
    })
      .then(res => {
        let isDelay = _.get(res, 'data.data.delay', false);
        if (isDelay) {
          message.success(`${description}报告开始导出，请稍后打开弹框查看历史记录`);
        } else {
          showSuccess && message.success(`成功导出${description}`);
          const fileName = _.get(res, 'data.data.fileName', '');
          if (fileName) {
            downloadAssetForm(fileName);
          }
        }
      })
      .catch(() => {
        message.error(`导出${description}失败`);
      });
  };

  exportChangeForm = (query, description, showSuccess = true) => {
    return exportChangeForm({
      ...query
    })
      .then(res => {
        showSuccess && message.success(`成功导出${description}`);
        const fileName = _.get(res, 'data.data.fileName', '');
        if (fileName) {
          downloadChangeForm(fileName);
        }
      })
      .catch(() => {
        message.error(`导出${description}失败`);
      });
  };

  getSiteExporter = (query, description) => {
    return (
      <a key="download" onClick={() => this.exportAssetForm(query, description, true)}>
        <img src={DownloadSvg} alt="download" />
      </a>
    );
  };

  getSiteChangeFormExporter = (query, description) => {
    return (
      <a key="download" onClick={() => this.exportChangeForm(query, description)}>
        <img src={DownloadSvg} alt="download" />
      </a>
    );
  };

  renderSiteInfo = (record = {}) => {
    const { url, ip, name, ipv6 } = record;
    const search = [
      url ? `exact:url="${url}"` : '',
      ip ? `exact:ip="${ip}"` : '',
      name ? `exact:name="${name}"` : '',
      ipv6 ? `exact:ipv6="${ipv6}"` : ''
    ]
      .filter(Boolean)
      .join(' && ');
    return (
      <a
        target="_blank"
        rel="noopener noreferrer"
        href={`/asset-manage?${encodeURIComponent(search)}`}
      >
        {!search ? '资产已被删除' : [name, url, ip, ipv6].filter(Boolean).join('|')}
      </a>
    );
  };
  renderVulLevelColorBlocks = vuls => {
    const levelMap = _.mapValues(_.groupBy(vuls, 'level'), value =>
      _.map(value, 'name')
        .filter(Boolean)
        .join(',')
    );
    const popoverContent = (
      <div style={{ maxWidth: 500, maxHeight: 300, overflow: 'auto', wordBreak: 'break-all' }}>
        {LEVEL_TYPES.map(typ => {
          return {
            level: typ,
            text: levelMap[typ] ? `${LEVEL_TEXT[typ]}: ${levelMap[typ]}` : ''
          };
        })
          .filter(i => i.text)
          .map((i, k) => (
            <div key={k} style={{ color: LEVEL_COLOR[i.level] }}>
              {i.text}
            </div>
          ))}
      </div>
    );
    const fatalCount = _.filter(vuls, { level: 'fatal' }).length;
    const highCount = _.filter(vuls, { level: 'high' }).length;
    const middleCount = _.filter(vuls, { level: 'middle' }).length;
    const lowCount = _.filter(vuls, { level: 'low' }).length;
    return (
      <Popover content={popoverContent}>
        <span className="color-bolcks">
          <i className={cn({ 'fatal-level-bg': fatalCount })}>{fatalCount ? fatalCount : null}</i>
          <i className={cn({ 'high-level-bg': highCount })}>{highCount ? highCount : null}</i>
          <i className={cn({ 'middle-level-bg': middleCount })}>
            {middleCount ? middleCount : null}
          </i>
          <i className={cn({ 'low-level-bg': lowCount })}>{lowCount ? lowCount : null}</i>
        </span>
      </Popover>
    );
  };

  showOneDayTaskModal = (site, siteQuery) => {
    const onedayTaskModalConfig = { visible: true };
    if (site) {
      onedayTaskModalConfig.targetCount = 1;
      onedayTaskModalConfig.sites = [site];
    } else {
      onedayTaskModalConfig.targetCount = _.get(this.state, 'countMap.withSuspectedVulSite', 0);
      onedayTaskModalConfig.siteQuery = siteQuery;
    }
    this.setState({ onedayTaskModalConfig });
  };

  downloadAllForm = () => {
    const { riskPorts, riskServices, riskComponents, hasOneDayModule } = this.state;
    const configs = [
      hasOneDayModule && [{ vulLevel: ['fatal', 'high', 'middle', 'low'] }, '存在漏洞的资产'],
      hasOneDayModule && [
        { suspectedOnedayLevel: ['fatal', 'high', 'middle', 'low'] },
        '有疑似漏洞的资产'
      ],
      [{ port: riskPorts }, '存在关键端口的资产'],
      [{ service: riskServices }, '存在关键服务的资产'],
      [{ component: riskComponents }, '存在关键组件的资产'],
      [
        {
          updated: [
            '0',
            moment()
              .endOf('day')
              .subtract(1, 'day')
              .format('YYYY-MM-DD HH:mm:ss')
          ]
        },
        `${TimeRangeMap[1]}未更新的资产`
      ],
      [
        {
          updated: [
            '0',
            moment()
              .endOf('day')
              .subtract(7, 'day')
              .format('YYYY-MM-DD HH:mm:ss')
          ]
        },
        `${TimeRangeMap[7]}未更新的资产`
      ],
      [
        {
          updated: [
            '0',
            moment()
              .endOf('day')
              .subtract(30, 'day')
              .format('YYYY-MM-DD HH:mm:ss')
          ]
        },
        `${TimeRangeMap[30]}未更新的资产`
      ],
      [
        {
          created: [
            moment()
              .endOf('day')
              .subtract(1, 'day')
              .format('YYYY-MM-DD HH:mm:ss'),
            moment().format('YYYY-MM-DD HH:mm:ss')
          ]
        },
        `${TimeRangeMap[1]}新增资产`
      ],
      [
        {
          created: [
            moment()
              .endOf('day')
              .subtract(7, 'day')
              .format('YYYY-MM-DD HH:mm:ss'),
            moment().format('YYYY-MM-DD HH:mm:ss')
          ]
        },
        `${TimeRangeMap[7]}新增资产`
      ],
      [
        {
          created: [
            moment()
              .endOf('day')
              .subtract(30, 'day')
              .format('YYYY-MM-DD HH:mm:ss'),
            moment().format('YYYY-MM-DD HH:mm:ss')
          ]
        },
        `${TimeRangeMap[30]}新增资产`
      ]
    ].filter(Boolean);
    const changeAssets = [1, 7, 30];
    configs
      .reduce(
        (t, config) => t.finally(() => this.exportAssetForm(...config, false)),
        Promise.resolve()
      )
      .then(() => {
        changeAssets
          .reduce(
            (t, config) =>
              t.finally(() =>
                this.exportChangeForm({ timeRange: config }, TimeRangeMap[config], false)
              ),
            Promise.resolve()
          )
          .then(() => {
            message.success('导出所有报表成功');
          })
          .catch(() => message.error('部分导出失败'));
      });
  };

  getOnedayLevelIcons = (stat, level) => {
    const LevelItem = CONSOLE_LEVEL_ICON_MAP[level];
    return (
      <span
        style={{
          ...(stat ? LevelItem.style : CONSOLE_LEVEL_ICON_MAP['disable'].style),
          padding: '3px',
          borderRadius: '2px'
        }}
      >
        {_.get(LevelItem, 'text', '')}
      </span>
    );
  };

  jumpToAssetByAffected = affected => {
    const { assetManageActions } = this.props;
    const affectKeys = ['component', 'service', 'os', 'title'];
    assetManageActions.resetQuery({
      search: affectKeys.map(key => `${key}="${affected}"`).join(' || ')
    });
    this.props.history.push('/asset-manage');
  };

  generateConfig = () => {
    const { riskPorts, riskServices, riskComponents, hasOneDayModule } = this.state;
    return [
      hasOneDayModule && {
        dataKey: 'withVulSite',
        icon: <img src={VulSvg} alt="vul" />,
        title: '存在漏洞的资产',
        columns: [
          {
            title: '风险值',
            dataIndex: 'risk'
          },
          {
            title: '资产信息',
            key: 'siteInfo',
            render: this.renderSiteInfo
          },
          {
            title: '更新时间',
            dataIndex: 'updated'
          },
          {
            title: '漏洞情况',
            dataIndex: 'vuls',
            render: this.renderVulLevelColorBlocks
          }
        ],
        loader: pagaition =>
          this.getSites({
            pagaition,
            query: { vulLevel: ['fatal', 'high', 'middle', 'low'] },
            key: 'withVulSite'
          }),
        getOperations: () => [
          this.getSiteOrJumper('vulLevel', ['fatal', 'high', 'middle', 'low']),
          this.getSiteExporter({ vulLevel: ['fatal', 'high', 'middle', 'low'] }, '存在漏洞的资产')
        ]
      },
      hasOneDayModule && {
        dataKey: 'withVulInfo',
        icon: <img src={VulInformationSvg} alt="information" />,
        title: '漏洞情报',
        countRender: ({ rest }) => `与您所管资产有关的情报${_.get(rest, 0, 0)}份`,
        columns: [
          {
            title: '漏洞情报',
            render: row => (
              <div>
                {this.getOnedayLevelIcons(
                  _.get(row, 'affectedSiteCount.real') || _.get(row, 'affectedSiteCount.suspect'),
                  row.level
                )}
                &nbsp;&nbsp;
                <span
                  style={
                    _.get(row, 'affectedSiteCount.real') || _.get(row, 'affectedSiteCount.suspect')
                      ? {}
                      : CONSOLE_ONEDAY_DISABLE_COLOR
                  }
                >
                  {row.name}
                </span>
                {_.get(row, 'status', null) && _.get(row, 'status', null) === 'NEW' ? (
                  <span
                    style={{
                      marginLeft: '5px',
                      padding: '2px 5px',
                      background: 'rgba(11,111,214, .1)',
                      color: '#0B6FD6'
                    }}
                  >
                    NEW
                  </span>
                ) : null}
              </div>
            )
          },
          {
            title: '真实影响资产',
            dataIndex: 'affectedSiteCount.real',
            render: (real, record) => {
              const { history, assetManageActions } = this.props;
              return (
                <a
                  style={real ? {} : CONSOLE_ONEDAY_DISABLE_COLOR}
                  onClick={() => {
                    history.push('/asset-manage');
                    assetManageActions.setState({
                      search: `vul="${record.name}"`,
                      // 点击搜索强制刷新
                      loadAssetListIndex: Date.now(),
                      pagaition: {
                        page: 1,
                        pageSize: 10
                      }
                    });
                  }}
                >
                  {real || 0}
                </a>
              );
            }
          },
          {
            title: '可能影响资产',
            dataIndex: 'affectedSiteCount.suspect',
            render: (suspect, record) => {
              const affected = _.get(record, 'affected', '-');

              return (
                <a
                  style={suspect ? {} : CONSOLE_ONEDAY_DISABLE_COLOR}
                  onClick={() => this.jumpToAssetByAffected(affected || '-')}
                >
                  {suspect || 0}
                </a>
              );
            }
          },
          {
            title: '更新时间',
            key: 'updated',
            render: row => (
              <span
                style={
                  _.get(row, 'affectedSiteCount.real') || _.get(row, 'affectedSiteCount.suspect')
                    ? {}
                    : CONSOLE_ONEDAY_DISABLE_COLOR
                }
              >
                {row.updated}
              </span>
            )
          }
        ],
        loader: pagaition => this.getOneday(pagaition),
        getOperations: () => [this.getOneDayJumper()]
      },
      hasOneDayModule && {
        dataKey: 'withVulInfo',
        icon: <img src={SuspectedSvg} alt="warning" />,
        title: '有疑似漏洞的资产',
        columns: [
          {
            title: '权重',
            dataIndex: 'weight'
          },
          {
            title: '资产信息',
            key: 'siteInfo',
            render: this.renderSiteInfo
          },
          {
            title: '更新时间',
            dataIndex: 'updated'
          },
          {
            title: '疑似漏洞',
            dataIndex: 'suspectedOnedays',
            render: this.renderVulLevelColorBlocks
          },
          {
            title: '操作',
            key: 'updated',
            fixed: 'right',
            render: site => {
              const { ip, ipv6 } = site;
              return (
                <span
                  onClick={ip || ipv6 ? () => this.showOneDayTaskModal(site) : () => {}}
                  style={{ whiteSpace: 'nowrap', cursor: ip || ipv6 ? 'pointer' : 'not-allowed' }}
                >
                  验证
                </span>
              );
            }
          }
        ],
        loader: pagaition =>
          this.getSites({
            pagaition,
            query: { suspectedOnedayLevel: ['fatal', 'high', 'middle', 'low'] },
            key: 'withSuspectedVulSite'
          }),
        getOperations: () => [
          this.getSiteOrJumper('suspectedOnedayLevel', ['fatal', 'high', 'middle', 'low']),
          this.getSiteExporter(
            { suspectedOnedayLevel: ['fatal', 'high', 'middle', 'low'] },
            '有疑似漏洞的资产'
          ),
          <img
            key="all"
            onClick={() =>
              this.showOneDayTaskModal(null, {
                query: {
                  suspectedOnedayLevel: ['fatal', 'high', 'middle', 'low']
                },
                description: '有疑似漏洞的资产'
              })
            }
            src={VerifySvg}
            alt="verify"
          />
        ]
      },
      {
        dataKey: 'withBlackPortSite',
        icon: <img src={RiskPortSvg} alt="port" />,
        title: '存在关键端口的资产',
        columns: [
          {
            title: '权重',
            dataIndex: 'weight'
          },
          {
            title: '资产信息',
            data: 'siteInfo',
            render: this.renderSiteInfo
          },
          {
            title: '更新时间',
            dataIndex: 'updated'
          },
          {
            title: '关键端口',
            dataIndex: 'portInfos',
            render: portInfos => {
              const siteRiskPorts = _.intersection(_.map(portInfos, 'port'), riskPorts);
              return siteRiskPorts.join(',');
            }
          }
        ],
        loader: pagaition => this.getRiskSites(pagaition, 'port', 'withBlackPortSite'),
        getOperations: () => [
          <a
            key="config"
            target="_blank"
            rel="noopener noreferrer"
            href="/asset-config/vulnerability-manage"
          >
            去配置
          </a>,
          this.getSiteOrJumper('port', riskPorts),
          this.getSiteExporter({ port: riskPorts }, '存在关键端口的资产')
        ]
      },
      {
        dataKey: 'withBlackServiceSite',
        icon: <img src={RiskServiceSvg} alt="server" />,
        title: '存在关键服务的资产',
        columns: [
          {
            title: '权重',
            dataIndex: 'weight'
          },
          {
            title: '资产信息',
            key: 'siteInfo',
            render: this.renderSiteInfo
          },
          {
            title: '更新时间',
            dataIndex: 'updated'
          },
          {
            title: '关键服务',
            dataIndex: 'portInfos',
            render: portInfos => {
              const siteRiskServices = _.filter(
                portInfos,
                portInfo => portInfo.service && _.includes(riskServices, portInfo.service)
              ).map(portInfo => [portInfo.port, portInfo.service].join('/'));
              return siteRiskServices.join(',');
            }
          }
        ],
        loader: pagaition => this.getRiskSites(pagaition, 'service', 'withBlackServiceSite'),
        getOperations: () => [
          <a
            key="config"
            target="_blank"
            rel="noopener noreferrer"
            href="/asset-config/vulnerability-manage"
          >
            去配置
          </a>,
          this.getSiteOrJumper('service', riskServices),
          this.getSiteExporter({ service: riskServices }, '存在关键服务的资产')
        ]
      },
      {
        dataKey: 'withBlackComponentSite',
        icon: <img src={RiskComponentSvg} alt="component" />,
        title: '存在关键组件的资产',
        columns: [
          {
            title: '权重',
            dataIndex: 'weight'
          },
          {
            title: '资产信息',
            key: 'siteInfo',
            render: this.renderSiteInfo
          },
          {
            title: '更新时间',
            dataIndex: 'updated'
          },
          {
            title: '关键组件',
            dataIndex: 'portInfos',
            render: portInfos => {
              const siteRiskComponents = [];
              _.forEach(portInfos, portInfo => {
                _.forEach(portInfo.components, component => {
                  let regex = new RegExp(riskComponents.join('|'), 'i');
                  if (regex.test(component.name)) {
                    siteRiskComponents.push(
                      [portInfo.port, portInfo.service, component.fullName]
                        .filter(Boolean)
                        .join('/')
                    );
                  }
                });
              });
              return siteRiskComponents.join(',');
            }
          }
        ],
        loader: pagaition => this.getRiskSites(pagaition, 'component', 'withBlackComponentSite'),
        getOperations: () => [
          <a
            key="config"
            target="_blank"
            rel="noopener noreferrer"
            href="/asset-config/vulnerability-manage"
          >
            去配置
          </a>,
          this.getSiteOrJumper('component', riskComponents),
          this.getSiteExporter({ component: riskComponents }, '存在关键组件的资产')
        ]
      },
      {
        dataKey: 'unUpdatedSite',
        icon: <img src={UnUpdatedSvg} alt="unUpdate" />,
        title: state => `${TimeRangeMap[_.get(state, 'timeRange', 7)]}未更新的资产`,
        columns: [
          {
            title: '权重',
            dataIndex: 'weight'
          },
          {
            title: '资产信息',
            key: 'siteInfo',
            render: this.renderSiteInfo
          },
          {
            title: '资产分类',
            dataIndex: 'assetCategories',
            render: assetCategories => {
              return _.map(assetCategories, ({ name, parent }) =>
                [_.get(parent, 'name'), name].filter(Boolean).join('/')
              ).join(',');
            }
          },
          {
            title: '操作系统',
            dataIndex: 'os'
          },
          {
            title: '更新时间',
            dataIndex: 'updated'
          }
        ],
        loader: (pagaition, { timeRange }) => {
          // eslint-disable-next-line
          timeRange || (timeRange = 7);
          this.setState({ notUpdatedTime: timeRange });
          const unUpdatedSiteKey = `unUpdatedSite${timeRange}`;
          const restKeys = [1, 7, 30].filter(key => key !== timeRange);
          for (let key of restKeys) {
            this.getSites({
              query: {
                updated: [
                  '0',
                  moment()
                    .endOf('day')
                    .subtract(key, 'day')
                    .format('YYYY-MM-DD HH:mm:ss')
                ]
              },
              key: `unUpdatedSite${key}`
            });
          }
          this.getSites({
            pagaition: { page: 1, pageSize: 200 },
            query: {
              updated: [
                '0',
                moment()
                  .endOf('day')
                  .subtract(timeRange, 'day')
                  .format('YYYY-MM-DD HH:mm:ss')
              ]
            },
            sort: {
              by: 'updated',
              direction: -1
            },
            key: unUpdatedSiteKey,
            timeNow: true
          });
          return this.getSites({
            pagaition,
            query: {
              updated: [
                '0',
                moment()
                  .endOf('day')
                  .subtract(timeRange, 'day')
                  .format('YYYY-MM-DD HH:mm:ss')
              ]
            },
            sort: {
              by: 'updated',
              direction: -1
            },
            key: unUpdatedSiteKey
          });
        },
        getOperations: ({ setState, state }) => {
          const timeRange = _.get(state, 'timeRange', 7);
          const updatedRange = [
            '0',
            moment()
              .endOf('day')
              .subtract(timeRange, 'day')
              .format('YYYY-MM-DD HH:mm:ss')
          ];
          const timeRangeRoute = {
            1: 'notUpdateIn1Days',
            7: 'notUpdateIn7Days',
            30: 'notUpdateIn30Days'
          };
          return [
            <Select
              key="range"
              buttonStyle="solid"
              defaultValue={7}
              style={{ width: 100 }}
              onChange={value => {
                setState({ timeRange: Number(value) });
                this.ListCardRef['unUpdatedSite'].current.resertTable();
              }}
              getPopupContainer={triggerNode => triggerNode.parentNode}
            >
              <Select.Option value={1}>今日</Select.Option>
              <Select.Option value={7}>近7日</Select.Option>
              <Select.Option value={30}>近30日</Select.Option>
            </Select>,
            this.getSiteRangeJumper('updatedRange', updatedRange),
            this.getSiteExporter(
              { updated: updatedRange },
              `${TimeRangeMap[timeRange]}未更新的资产`
            ),
            <img
              key="dispatch"
              onClick={() =>
                this.props.history.push({
                  pathname: '/task-list/add-task',
                  state: {
                    type: timeRangeRoute[timeRange],
                    description: `${TimeRangeMap[timeRange]}未更新的资产`
                  }
                })
              }
              src={DetectSvg}
              alt="detect"
            />
          ];
        }
      },
      {
        dataKey: 'newSite',
        icon: <img src={NewAddSvg} alt="new" />,
        title: state => `${TimeRangeMap[_.get(state, 'timeRange', 7)]}新增资产`,
        columns: [
          {
            title: '权重',
            dataIndex: 'weight'
          },
          {
            title: '资产信息',
            key: 'siteInfo',
            render: this.renderSiteInfo
          },
          {
            title: '资产分类',
            dataIndex: 'assetCategories',
            render: assetCategories => {
              return _.map(assetCategories, ({ name, parent }) =>
                [_.get(parent, 'name'), name].filter(Boolean).join('/')
              ).join(',');
            }
          },
          {
            title: '操作系统',
            dataIndex: 'os'
          },
          {
            title: '创建时间',
            dataIndex: 'created'
          }
        ],
        loader: (pagaition, { timeRange }) => {
          // eslint-disable-next-line
          timeRange || (timeRange = 7);
          const newSiteKey = `newSite${timeRange}`;
          const restKeys = [1, 7, 30].filter(key => key !== timeRange);
          for (let key of restKeys) {
            this.getSites({
              query: {
                created: [
                  moment()
                    .endOf('day')
                    .subtract(key, 'day')
                    .format('YYYY-MM-DD HH:mm:ss'),
                  moment().format('YYYY-MM-DD HH:mm:ss')
                ]
              },
              key: `newSite${key}`
            });
          }
          return this.getSites({
            pagaition,
            query: {
              created: [
                moment()
                  .endOf('day')
                  .subtract(timeRange, 'day')
                  .format('YYYY-MM-DD HH:mm:ss'),
                moment().format('YYYY-MM-DD HH:mm:ss')
              ]
            },
            sort: { by: 'created', direction: -1 },
            key: newSiteKey
          });
        },
        getOperations: ({ setState, state }) => {
          const timeRange = _.get(state, 'timeRange', 7);
          const createdRange = [
            moment()
              .endOf('day')
              .subtract(timeRange, 'day')
              .format('YYYY-MM-DD HH:mm:ss'),
            moment().format('YYYY-MM-DD HH:mm:ss')
          ];
          return [
            <Select
              key="range"
              buttonStyle="solid"
              defaultValue={7}
              style={{ width: 100 }}
              onChange={value => {
                setState({ timeRange: Number(value) });
                this.ListCardRef['newSite'].current.resertTable();
              }}
              getPopupContainer={triggerNode => triggerNode.parentNode}
            >
              <Select.Option value={1}>今日</Select.Option>
              <Select.Option value={7}>近7日</Select.Option>
              <Select.Option value={30}>近30日</Select.Option>
            </Select>,
            this.getSiteRangeJumper('createdRange', createdRange),
            this.getSiteExporter({ created: createdRange }, `${TimeRangeMap[timeRange]}新增资产`)
          ];
        }
      }
    ].filter(Boolean);
  };

  render() {
    const {
      lastUpdatedAt,
      countMap,
      onedayTaskModalConfig,
      detectionTaskModal,
      detectionSiteQuery,
      hasOneDayModule,
      ips
    } = this.state;

    const listCardConfigs = this.generateConfig();
    listCardConfigs.map(r => {
      this.ListCardRef[r.dataKey] = React.createRef();
    });
    let riskItemCount = _.sum(_.values(countMap));
    return (
      <div className="console">
        <div className="console-top">
          <div className="time">
            <img src={UpdateSvg} alt="" />
            最近一次更新时间：
            {lastUpdatedAt ? moment(lastUpdatedAt).format('YYYY-MM-DD HH:mm:ss') : '-'}
          </div>
          <div className="risks">
            {riskItemCount ? (
              <div className="summary risk">
                <img src={RiskSvg} className="bg" alt="" />
                <div className="desc">您需要关注以下问题</div>
                <div className="count">
                  <div className="value">{riskItemCount}</div>
                  <div className="count-desc">风险事项</div>
                </div>
                <div className="sug">当前风险点较多，请及时进行风险修复。</div>
              </div>
            ) : (
              <div className="summary safe">
                <img src={SafeSvg} className="bg" alt="safe" />
                <div className="desc">您需要关注以下问题</div>
                <div className="safe-desc">暂未发现风险</div>
                <div className="sug">当前风险点较多，请及时进行风险修复。</div>
              </div>
            )}

            <div className="risk-cards">
              {riskCardConfigs
                .slice(hasOneDayModule ? 0 : 1, riskCardConfigs.length)
                .map((group = [], index) => (
                  <div className="risk-card" key={`console-risk-card-${index}`}>
                    {group.map(config => (
                      <div className="item" key={config.dataKey}>
                        <div className="value">{_.get(countMap, config.dataKey, 0)}</div>
                        <div className="title">{config.title}</div>
                      </div>
                    ))}
                  </div>
                ))}
            </div>
            <div className="download-all">
              <img src={DownloadAllSvg} alt="download" />
              <Button type="primary" onClick={this.downloadAllForm} className="button-forwards">
                下载所有报表
              </Button>
            </div>
          </div>
        </div>

        <div className="list-cards">
          {listCardConfigs.map((config, index) => (
            <ListCard
              key={index}
              {...config}
              updatedAt={lastUpdatedAt}
              ref={this.ListCardRef[config.dataKey]}
            />
          ))}
          <SitesChangeCard
            renderSiteInfo={this.renderSiteInfo}
            setProps={this.setState.bind(this)}
            getSiteExporter={this.getSiteChangeFormExporter}
            className={`${hasOneDayModule && 'flex-all'}`}
          />
        </div>
        <OnedayTaskModal
          {...onedayTaskModalConfig}
          onClose={() => this.setState({ onedayTaskModalConfig: { visible: false } })}
        />
        <DetectionTaskModal
          siteQuery={detectionSiteQuery}
          visible={detectionTaskModal}
          selectedTargets={ips}
          onVisibleChange={detectionTaskModal => this.setState({ detectionTaskModal })}
          allSite={true}
          allSiteTitle={`${TimeRangeMap[this.state.notUpdatedTime]}未更新的资产`}
        />
      </div>
    );
  }
}

Console.propTypes = {
  history: PropTypes.object,
  assetManageActions: PropTypes.object,
  modules: PropTypes.array
};

const mapStateToProps = state => {
  return {
    modules: _.get(state, 'auth.cert.modules', [])
  };
};

const mapDispatchToProps = dispatch => {
  return {
    assetManageActions: bindActionCreators(assetManageActions, dispatch)
  };
};

export default connect(
  mapStateToProps,
  mapDispatchToProps
)(Console);
